package net.xdclass.controller;

import lombok.extern.slf4j.Slf4j;
import net.xdclass.enums.ShortLinkStateEnum;
import net.xdclass.service.ShortLinkService;
import net.xdclass.util.CommonUtil;
import net.xdclass.vo.ShortLinkVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.regex.Matcher;

/**
 * 短链跳转
 * @author 小二
 */
@RestController
@Slf4j
public class LinkApiController {

    @Autowired
    private ShortLinkService shortLinkService;

    /**
     * 解析 301还是302，这边是返回http code是302
     * <p>
     * 知识点一，为什么要用 301 跳转而不是 302 呐？
     * <p>
     * 301 是永久重定向，302 是临时重定向。
     * <p>
     * 短地址一经生成就不会变化，所以用 301 是同时对服务器压力也会有一定减少
     * <p>
     * 但是如果使用了 301，无法统计到短地址被点击的次数。
     * <p>
     * 所以选择302虽然会增加服务器压力，但是有很多数据可以获取进行分析
     *
     * @param shortLinkCode
     * @return
     */
    @GetMapping("/{shortLinkCode}")
    public void dispatch(@PathVariable("shortLinkCode") String shortLinkCode, HttpServletRequest request, HttpServletResponse response) {
        try {
            log.info("shortLinkCode : " + shortLinkCode);
            if (isLetterDigit(shortLinkCode)) {
                // 查找短链
                ShortLinkVO shortLinkVO = shortLinkService.parseShortLinkCode(shortLinkCode);
                if (isVisitable(shortLinkVO)) {
                    // 移除URL前缀
                    String originalUrl = CommonUtil.removeUrlPrefix(shortLinkVO.getOriginalUrl());

                    // 短链码可用 302 跳转
                    response.setHeader("Location", originalUrl);

                    response.setStatus(HttpStatus.FOUND.value());

                } else {
                    // 不可用 404 跳转
                    response.setStatus(HttpStatus.NOT_FOUND.value());
                }
            }
        } catch (Exception e) {
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
        }
    }

    /**
     * 判断短链是不是可用
     * @param shortLinkVO
     * @return
     */
    private static boolean isVisitable(ShortLinkVO shortLinkVO) {

        if (shortLinkVO == null) {
            return false;
        }

        long expireTime = shortLinkVO.getExpired().getTime();

        if (expireTime > CommonUtil.getCurrentTimestamp() || expireTime == -1) {
            return ShortLinkStateEnum.ACTIVE.name().equalsIgnoreCase(shortLinkVO.getState());
        }
        return false;
    }

    /**
     * 匹配短链码是否合规
     * 只包含数字和字母
     * @param code
     * @return
     */
    private static boolean isLetterDigit(String code) {
        String regex = "^[a-z0-9A-Z]+$";
        return code.matches(regex);
    }

}
